/**
 * Copyright (c) 2006-2015, JGraph Ltd
 * Copyright (c) 2006-2015, Gaudenz Alder
 */
var mxLog =
    {
        /**
         * Class: mxLog
         *
         * A singleton class that implements a simple console.
         *
         * Variable: consoleName
         *
         * Specifies the name of the console window. Default is 'Console'.
         */
        consoleName: 'Console',

        /**
         * Variable: TRACE
         *
         * Specified if the output for <enter> and <leave> should be visible in the
         * console. Default is false.
         */
        TRACE: false,

        /**
         * Variable: DEBUG
         *
         * Specifies if the output for <debug> should be visible in the console.
         * Default is true.
         */
        DEBUG: true,

        /**
         * Variable: WARN
         *
         * Specifies if the output for <warn> should be visible in the console.
         * Default is true.
         */
        WARN: true,

        /**
         * Variable: buffer
         *
         * Buffer for pre-initialized content.
         */
        buffer: '',

        /**
         * Function: init
         *
         * Initializes the DOM node for the console. This requires document.body to
         * point to a non-null value. This is called from within <setVisible> if the
         * log has not yet been initialized.
         */
        init: function()
        {
            if (mxLog.window == null && document.body != null)
            {
                var title = mxLog.consoleName + ' - mxGraph ' + mxClient.VERSION;

                // Creates a table that maintains the layout
                var table = document.createElement('table');
                table.setAttribute('width', '100%');
                table.setAttribute('height', '100%');

                var tbody = document.createElement('tbody');
                var tr = document.createElement('tr');
                var td = document.createElement('td');
                td.style.verticalAlign = 'top';

                // Adds the actual console as a textarea
                mxLog.textarea = document.createElement('textarea');
                mxLog.textarea.setAttribute('wrap', 'off');
                mxLog.textarea.setAttribute('readOnly', 'true');
                mxLog.textarea.style.height = '100%';
                mxLog.textarea.style.resize = 'none';
                mxLog.textarea.value = mxLog.buffer;

                // Workaround for wrong width in standards mode
                if (mxClient.IS_NS && document.compatMode != 'BackCompat')
                {
                    mxLog.textarea.style.width = '99%';
                }
                else
                {
                    mxLog.textarea.style.width = '100%';
                }

                td.appendChild(mxLog.textarea);
                tr.appendChild(td);
                tbody.appendChild(tr);

                // Creates the container div
                tr = document.createElement('tr');
                mxLog.td = document.createElement('td');
                mxLog.td.style.verticalAlign = 'top';
                mxLog.td.setAttribute('height', '30px');

                tr.appendChild(mxLog.td);
                tbody.appendChild(tr);
                table.appendChild(tbody);

                // Adds various debugging buttons
                mxLog.addButton('Info', function (evt)
                {
                    mxLog.info();
                });

                mxLog.addButton('DOM', function (evt)
                {
                    var content = mxUtils.getInnerHtml(document.body);
                    mxLog.debug(content);
                });

                mxLog.addButton('Trace', function (evt)
                {
                    mxLog.TRACE = !mxLog.TRACE;

                    if (mxLog.TRACE)
                    {
                        mxLog.debug('Tracing enabled');
                    }
                    else
                    {
                        mxLog.debug('Tracing disabled');
                    }
                });

                mxLog.addButton('Copy', function (evt)
                {
                    try
                    {
                        mxUtils.copy(mxLog.textarea.value);
                    }
                    catch (err)
                    {
                        mxUtils.alert(err);
                    }
                });

                mxLog.addButton('Show', function (evt)
                {
                    try
                    {
                        mxUtils.popup(mxLog.textarea.value);
                    }
                    catch (err)
                    {
                        mxUtils.alert(err);
                    }
                });

                mxLog.addButton('Clear', function (evt)
                {
                    mxLog.textarea.value = '';
                });

                // Cross-browser code to get window size
                var h = 0;
                var w = 0;

                if (typeof(window.innerWidth) === 'number')
                {
                    h = window.innerHeight;
                    w = window.innerWidth;
                }
                else
                {
                    h = (document.documentElement.clientHeight || document.body.clientHeight);
                    w = document.body.clientWidth;
                }

                mxLog.window = new mxWindow(title, table, Math.max(0, w - 320), Math.max(0, h - 210), 300, 160);
                mxLog.window.setMaximizable(true);
                mxLog.window.setScrollable(false);
                mxLog.window.setResizable(true);
                mxLog.window.setClosable(true);
                mxLog.window.destroyOnClose = false;

                // Workaround for ignored textarea height in various setups
                if (((mxClient.IS_NS || mxClient.IS_IE) && !mxClient.IS_GC &&
                    !mxClient.IS_SF && document.compatMode != 'BackCompat') ||
                    document.documentMode == 11)
                {
                    var elt = mxLog.window.getElement();

                    var resizeHandler = function(sender, evt)
                    {
                        mxLog.textarea.style.height = Math.max(0, elt.offsetHeight - 70) + 'px';
                    };

                    mxLog.window.addListener(mxEvent.RESIZE_END, resizeHandler);
                    mxLog.window.addListener(mxEvent.MAXIMIZE, resizeHandler);
                    mxLog.window.addListener(mxEvent.NORMALIZE, resizeHandler);

                    mxLog.textarea.style.height = '92px';
                }
            }
        },

        /**
         * Function: info
         *
         * Writes the current navigator information to the console.
         */
        info: function()
        {
            mxLog.writeln(mxUtils.toString(navigator));
        },

        /**
         * Function: addButton
         *
         * Adds a button to the console using the given label and function.
         */
        addButton: function(lab, funct)
        {
            var button = document.createElement('button');
            mxUtils.write(button, lab);
            mxEvent.addListener(button, 'click', funct);
            mxLog.td.appendChild(button);
        },

        /**
         * Function: isVisible
         *
         * Returns true if the console is visible.
         */
        isVisible: function()
        {
            if (mxLog.window != null)
            {
                return mxLog.window.isVisible();
            }

            return false;
        },


        /**
         * Function: show
         *
         * Shows the console.
         */
        show: function()
        {
            mxLog.setVisible(true);
        },

        /**
         * Function: setVisible
         *
         * Shows or hides the console.
         */
        setVisible: function(visible)
        {
            if (mxLog.window == null)
            {
                mxLog.init();
            }

            if (mxLog.window != null)
            {
                mxLog.window.setVisible(visible);
            }
        },

        /**
         * Function: enter
         *
         * Writes the specified string to the console
         * if <TRACE> is true and returns the current
         * time in milliseconds.
         *
         * Example:
         *
         * (code)
         * mxLog.show();
         * var t0 = mxLog.enter('Hello');
         * // Do something
         * mxLog.leave('World!', t0);
         * (end)
         */
        enter: function(string)
        {
            if (mxLog.TRACE)
            {
                mxLog.writeln('Entering '+string);

                return new Date().getTime();
            }
        },

        /**
         * Function: leave
         *
         * Writes the specified string to the console
         * if <TRACE> is true and computes the difference
         * between the current time and t0 in milliseconds.
         * See <enter> for an example.
         */
        leave: function(string, t0)
        {
            if (mxLog.TRACE)
            {
                var dt = (t0 != 0) ? ' ('+(new Date().getTime() - t0)+' ms)' : '';
                mxLog.writeln('Leaving '+string+dt);
            }
        },

        /**
         * Function: debug
         *
         * Adds all arguments to the console if <DEBUG> is enabled.
         *
         * Example:
         *
         * (code)
         * mxLog.show();
         * mxLog.debug('Hello, World!');
         * (end)
         */
        debug: function()
        {
            if (mxLog.DEBUG)
            {
                mxLog.writeln.apply(this, arguments);
            }
        },

        /**
         * Function: warn
         *
         * Adds all arguments to the console if <WARN> is enabled.
         *
         * Example:
         *
         * (code)
         * mxLog.show();
         * mxLog.warn('Hello, World!');
         * (end)
         */
        warn: function()
        {
            if (mxLog.WARN)
            {
                mxLog.writeln.apply(this, arguments);
            }
        },

        /**
         * Function: write
         *
         * Adds the specified strings to the console.
         */
        write: function()
        {
            var string = '';

            for (var i = 0; i < arguments.length; i++)
            {
                string += arguments[i];

                if (i < arguments.length - 1)
                {
                    string += ' ';
                }
            }

            if (mxLog.textarea != null)
            {
                mxLog.textarea.value = mxLog.textarea.value + string;

                // Workaround for no update in Presto 2.5.22 (Opera 10.5)
                if (navigator.userAgent.indexOf('Presto/2.5') >= 0)
                {
                    mxLog.textarea.style.visibility = 'hidden';
                    mxLog.textarea.style.visibility = 'visible';
                }

                mxLog.textarea.scrollTop = mxLog.textarea.scrollHeight;
            }
            else
            {
                mxLog.buffer += string;
            }
        },

        /**
         * Function: writeln
         *
         * Adds the specified strings to the console, appending a linefeed at the
         * end of each string.
         */
        writeln: function()
        {
            var string = '';

            for (var i = 0; i < arguments.length; i++)
            {
                string += arguments[i];

                if (i < arguments.length - 1)
                {
                    string += ' ';
                }
            }

            mxLog.write(string + '\n');
        }

    };
